
package com.feib.soeasy.action;

import java.io.File;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import com.feib.soeasy.model.FormatDefinition;
import com.feib.soeasy.model.Group;
import com.feib.soeasy.model.LabelValue;
import com.feib.soeasy.model.UploadFile;
import com.feib.soeasy.pagination.PaginatedList;
import com.feib.soeasy.service.AsyncService;
import com.feib.soeasy.service.FormatDefinitionService;
import com.feib.soeasy.service.GroupService;
import com.feib.soeasy.service.UploadFileService;
import com.feib.soeasy.util.UserUtil;

import net.sourceforge.stripes.action.DefaultHandler;
import net.sourceforge.stripes.action.DontBind;
import net.sourceforge.stripes.action.FileBean;
import net.sourceforge.stripes.action.ForwardResolution;
import net.sourceforge.stripes.action.LocalizableMessage;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.integration.spring.SpringBean;
import net.sourceforge.stripes.validation.DateTypeConverter;
import net.sourceforge.stripes.validation.LocalizableError;
import net.sourceforge.stripes.validation.Validate;
import net.sourceforge.stripes.validation.ValidateNestedProperties;
import net.sourceforge.stripes.validation.ValidationError;
import net.sourceforge.stripes.validation.ValidationErrorHandler;
import net.sourceforge.stripes.validation.ValidationErrors;


/**
 * @title (#)Soez1012ActionBean.java<br>
 * @description 帳單整批上傳作業 Controller<br>
 * @author Jimmy Liu<br>
 * @version 1.0.0 2010/11/25
 * @copyright Far Eastern International Bank Copyright (c) 2010<br>
 * @2010/11/21 create by Jimmy Liu<br>
 */
public class Soez1012ActionBean extends BaseActionBean implements ValidationErrorHandler {

    private static final String DEFAULT_JSP = "/WEB-INF/views/soez1012/soez1012.jsp";

    /**
     * 業者代號查詢畫面
     */
    private static final String AJAX_QUERY_GROUP_JSP = "/WEB-INF/views/soez1012/groupPopUpList.jsp";

    /**
     * [業者代號]改變後觸發重製[收款類別]選項結果
     */
    private static final String AJAX_FORMT_DEF_OPTIONS_JSP = "/WEB-INF/views/soez1012/formatDefinitionOptions.jsp";
    
    private static String separator = "/";

    /**
     * 上傳紀錄
     */
    @ValidateNestedProperties({
        @Validate(field="group.groupNo", required=true, on={"doUpload"}  )
        , @Validate(field="formatDefinition.formatDefinitionPk", required=true, on={"doUpload"} )
        , @Validate(field="uploadDate", converter=DateTypeConverter.class )
    })
    private UploadFile uploadFile = new UploadFile();

    /**
     * Client端上傳的檔案
     */
    @Validate(required=true, on={"doUpload"} )
    private FileBean filedata; 

    /**
     * 帳單業者查詢條件
     */
    private Group qryGroup;

    /**
     * 帳單業者查詢結果
     */
    private PaginatedList<Group> queryGroupResult;

    /**
     * 收款類別選單
     */
    private List<LabelValue> formatDefinitionoOptions;

    /**
     * 回應訊息
     */
    private String message;

    /**
     * 訊息抬頭
     */
    private String messageTitle;

    @SpringBean("formatDefinitionService")
    private FormatDefinitionService formatDefinitionService;

    @SpringBean("groupService")
    private GroupService groupService;

    @SpringBean("uploadFileService")
    private UploadFileService uploadFileService;

    @SpringBean("fileImportDestination")
    private String fileImportDestination;

    @SpringBean("fileDownloadDestination")
    private String fileDownloadDestination;

    @SpringBean("asyncService")
    private AsyncService asyncService;
    
    
    @DontBind
    @DefaultHandler
    public Resolution doDefault()
    {
        logger.debug("Enter doDefault mehtod.");
        if (!UserUtil.isBankGroup())
        {
            Group group = new Group();
            group.setGroupNo(UserUtil.getUserGroup().getGroupNo());
            group.setGroupPk(UserUtil.getUserGroup().getGroupPk());
            this.uploadFile.setGroup(group);
        }
        return new ForwardResolution(DEFAULT_JSP); 
    }

    public Resolution doUpload()
    {
        logger.debug("Enter doUpload mehtod.");
        StringBuffer logNote = new StringBuffer();
        try {

            //如果不是銀行端，強迫條件要加入帳單業者限制
            if (!UserUtil.isBankGroup())
            {
                Group group = new Group();
                group.setGroupNo(UserUtil.getUserGroup().getGroupNo());
                group.setGroupPk(UserUtil.getUserGroup().getGroupPk());
                this.uploadFile.setGroup(group);
            }
            
            // Client 端的檔案名稱
            String fileName = filedata.getFileName();
            logNote.append("檔案名稱: ").append(fileName).append("。");
            
            // 計算檔案大小
            try {
                long fileSize = filedata.getSize();
                if (fileSize > 1048576)
                {
                    logNote.append("大小: ").append(fileSize/1048576).append(" Mb。");
                }
                else if (fileSize > 1024)
                {
                    logNote.append("大小: ").append(fileSize/1024).append(" Kb。");
                }
                else
                {
                    logNote.append("大小: ").append(fileSize).append(" bytes。");
                }
            }
            catch (Exception e) {
                // do nothing.
            }
            
            // 存放在 Server 上的名稱
            String fileNameOnServer = UUID.randomUUID().toString();
            
            // 存放目錄
            String toDest = fileImportDestination + separator + this.uploadFile.getGroup().getGroupNo()+ separator;            
            File toFile = new File(toDest);
            // 目錄不存在則建立目錄
            if (!toFile.exists())
            {
                try {
                    toFile.mkdirs();
                }
                catch (Exception e) {
                    //無法建立匯入目錄
                    throw new Exception(new LocalizableMessage("can.not.create.import.folder", toFile.getAbsolutePath()).getMessage(getContext().getLocale()), e);
                }
            }

            // 繳費單(合併)下載目錄, ex: c:/soeaxy/download/29092176001/bill/merge/
            String downloadDest = this.fileDownloadDestination + separator + this.uploadFile.getGroup().getGroupNo() + separator + "bill"+separator+"merge" + separator;            
            File downloadFile = new File(downloadDest);
            // 目錄不存在則建立目錄
            if (!downloadFile.exists())
            {
                try {
                    downloadFile.mkdirs();
                }
                catch (Exception e) {
                    //無法建立匯入目錄
                    throw new Exception(new LocalizableMessage("can.not.create.download.folder", downloadFile.getAbsolutePath()).getMessage(getContext().getLocale()), e);
                }
            }

            // 存放檔案的完整路徑檔名
            toDest = toDest + fileNameOnServer; 
            toFile = new File(toDest);

            // 從 Temp 搬到 存放路徑
            filedata.save(toFile);
            

            // 紀錄上傳資訊於Table中
            Group group = this.groupService.findByExactGroupNo(this.uploadFile.getGroup().getGroupNo());
            uploadFile.setGroup(group);
            uploadFile.setFileName(fileName);
            uploadFile.setFilePathOnServer(toDest);

            // '-繳費單合併檔.pdf'
            
            //避免同樣檔名傳上來所產生出來的檔案會被覆蓋，加入時間(數字)條件, Jimmy Liu, 2012.03.28
            //FEIB_Output-繳費單合併檔.pdf    FEIB_Output-繳費單合併檔20120501121212001.pdf
            //String mergePdfTitle = "-" + new LocalizableMessage("Soez1012.action.merge.bill").getMessage(getContext().getLocale()) + ".pdf";
            DateFormat yyyymmddhhmmssms = new SimpleDateFormat("yyyyMMddHHmmssS");
            String mergePdfTitle = "-" + new LocalizableMessage("Soez1012.action.merge.bill").getMessage(getContext().getLocale())+ yyyymmddhhmmssms.format(new Date()) + ".pdf";

            String pdfFileName = fileName + mergePdfTitle;
            
            //黃郁珊配合中租檔案命名原則修改
            if ( -1 != fileName.lastIndexOf("."))
            {
                pdfFileName = fileName.substring(0, fileName.lastIndexOf(".")) + mergePdfTitle;
            }
            
            uploadFile.setPdfFileName(pdfFileName);
            String pdfFilePathOnServer = downloadDest + pdfFileName ;
            uploadFile.setPdfFilePathOnServer(pdfFilePathOnServer);

            uploadFile = uploadFileService.add(uploadFile);

            // 呼叫 匯入程式
            asyncService.doFileImport(uploadFile.getUploadFilePk());
            
            super.addAccessLog("上傳成功！ "+ logNote.toString(), false);

            message = new LocalizableMessage("Soez1012.action.doUpload.success").getMessage(getContext().getLocale()); // 檔案已上傳成功，待系統檢核完後將自動寄送檢核結果
            this.messageTitle = new LocalizableMessage("message.title").getMessage(getContext().getLocale()); // 訊息
            
        }
        catch (Exception e) {
            super.addAccessLog("上傳失敗！ "+ logNote.toString(), false);
            logger.error("帳單整批上傳作業錯誤(Soez1012ActionBean.doUpload):", e);
            message = e.getMessage();
            this.messageTitle = new LocalizableMessage("error.title").getMessage(getContext().getLocale()); // 錯誤
        }

        return new ForwardResolution(DEFAULT_JSP); 
    }

    /**
     * data binding 錯誤處理<br>
     * Allows the ActionBean to influence what happens when validation errors occur during
     * validation and binding.
     * 
     * @param errors the set of validation errors generated during validation and binding
     * @retur nnull, or a Resolution specifying what should happen next if non-standard
     *        behaviour is desired
     * @throws Exception may throw any exception, but this will generally result in a
     *         ServletException being thrown on up the stack
     */
    @Override
    public Resolution handleValidationErrors(ValidationErrors errors) throws Exception {

        if ("doUpload".equalsIgnoreCase(this.getContext().getEventName()))
        {
            StringBuffer msgBuffer = new StringBuffer();
            for (List<ValidationError> fieldErrors : errors.values()) {
                for (ValidationError error : fieldErrors) {
                    msgBuffer.append("<div class=\"error\">");
                    msgBuffer.append(error.getMessage(getContext().getLocale()));
                    msgBuffer.append("</div>");
                }
            }

            this.messageTitle = new LocalizableMessage("error.title").getMessage(getContext().getLocale()); // 錯誤

            this.message = msgBuffer.toString();

            return new ForwardResolution(DEFAULT_JSP);
        }

        return super.handleValidationErrors(errors);
    }

    /**
     * 帳單業者查詢
     * @return
     */
    public Resolution doAjaxQueryGroups()
    {
        logger.debug("Enter doAjaxQueryGroups mehtod.");
        try {
            //如果不是銀行端，則查詢條件要加入帳單業者限制
            if (!UserUtil.isBankGroup())
            {
                throw new Exception(new LocalizableMessage("no.authority").getMessage(getContext().getLocale()));
            }


            //USER未輸入查詢條件，所以查詢物件會是NULL(查詢物件不可為NULL)
            if (null == qryGroup)
                qryGroup = new Group();

            //呼叫服務查詢
            queryGroupResult = groupService.queryByGroupExcludeBank(qryGroup, queryGroupResult);
        }
        catch (Exception e) {
            logger.error("帳單上傳記錄查詢-帳單業者查詢錯誤(Soez9004ActionBean.doAjaxQueryGroups):", e);

            // 轉換錯誤訊息
            ValidationErrors errors = new ValidationErrors();
            errors.addGlobalError(new LocalizableError("ajax.query.exception") );
            getContext().setValidationErrors(errors);
            // 回傳 錯誤 HTML fragments
            return super.errorsToHtmlStreams(errors);
        }

        return new ForwardResolution(AJAX_QUERY_GROUP_JSP);
    }

    public Resolution doAjaxGroupNoChange()
    {
        return new ForwardResolution(AJAX_FORMT_DEF_OPTIONS_JSP);
    }


    /**
     * @return the uploadFile
     */
    public UploadFile getUploadFile() {
        return uploadFile;
    }


    /**
     * @param uploadFile the uploadFile to set
     */
    public void setUploadFile(UploadFile uploadFile) {
        this.uploadFile = uploadFile;
    }

    /**
     * @return the formatDefinitionoOptions
     */
    public List<LabelValue> getFormatDefinitionoOptions() {
        if (null == this.formatDefinitionoOptions)
        {
            //如果不是銀行端，則查詢條件要加入帳單業者限制
            if (!UserUtil.isBankGroup())
            {
                // 查詢條件
                FormatDefinition formatDefinition = new FormatDefinition();
                Group group = new Group();
                group.setGroupPk(UserUtil.getUserGroup().getGroupPk());
                formatDefinition.setGroup(group);
                formatDefinition.setFormatType(new Integer(1));
                formatDefinition.setDeleted(Boolean.FALSE);
                formatDefinitionoOptions = formatDefinitionService.findLabelValueByFormatDefinition(formatDefinition, false);
            }
            else
            {
                // 銀行端，看是否有群組代碼，若沒有則回傳空陣列
                if (null != this.getUploadFile() && null != this.getUploadFile().getGroup())
                {
                    // 查詢條件
                    FormatDefinition formatDefinition = new FormatDefinition();
                    formatDefinition.setGroup(this.getUploadFile().getGroup());
                    formatDefinition.setDeleted(Boolean.FALSE);
                    formatDefinition.setFormatType(new Integer(1));
                    formatDefinitionoOptions = formatDefinitionService.findLabelValueByFormatDefinition(formatDefinition, false);
                }
                else
                {
                    this.formatDefinitionoOptions = new ArrayList<LabelValue>();                    
                }

            }

        }
        return formatDefinitionoOptions;
    }


    /**
     * @param formatDefinitionoOptions the formatDefinitionoOptions to set
     */
    public void setFormatDefinitionoOptions(List<LabelValue> formatDefinitionoOptions) {
    	this.formatDefinitionoOptions = formatDefinitionoOptions;
    }


    /**
     * @return the filedata
     */
    public FileBean getFiledata() {
    	return filedata;
    }


    /**
     * @param filedata the filedata to set
     */
    public void setFiledata(FileBean filedata) {
    	this.filedata = filedata;
    }


    /**
     * @return the qryGroup
     */
    public Group getQryGroup() {
    	return qryGroup;
    }


    /**
     * @param qryGroup the qryGroup to set
     */
    public void setQryGroup(Group qryGroup) {
    	this.qryGroup = qryGroup;
    }


    /**
     * @return the queryGroupResult
     */
    public PaginatedList<Group> getQueryGroupResult() {
    	return queryGroupResult;
    }


    /**
     * @param queryGroupResult the queryGroupResult to set
     */
    public void setQueryGroupResult(PaginatedList<Group> queryGroupResult) {
    	this.queryGroupResult = queryGroupResult;
    }


    /**
     * @return the message
     */
    public String getMessage() {
    	return message;
    }


    /**
     * @param message the message to set
     */
    public void setMessage(String message) {
    	this.message = message;
    }


    /**
     * @return the messageTitle
     */
    public String getMessageTitle() {
    	return messageTitle;
    }


    /**
     * @param messageTitle the messageTitle to set
     */
    public void setMessageTitle(String messageTitle) {
    	this.messageTitle = messageTitle;
    }

    public void setFormatDefinitionService(
    		FormatDefinitionService formatDefinitionService) {
    	this.formatDefinitionService = formatDefinitionService;
    }

    public void setGroupService(GroupService groupService) {
    	this.groupService = groupService;
    }

    public void setUploadFileService(UploadFileService uploadFileService) {
    	this.uploadFileService = uploadFileService;
    }

    public void setFileImportDestination(String fileImportDestination) {
    	this.fileImportDestination = fileImportDestination;
    }

    public void setFileDownloadDestination(String fileDownloadDestination) {
    	this.fileDownloadDestination = fileDownloadDestination;
    }

    public void setAsyncService(AsyncService asyncService) {
    	this.asyncService = asyncService;
    }
}
